﻿using System;
using System.Collections.Generic;
using Gameplay.PVE.Utils;
using UnityEngine;
using UnityEngine.AI;
using Yoozoo.Gta.Common;
using Yoozoo.Libs;
using Yoozoo.Managers;
using Random = UnityEngine.Random;

namespace Gameplay.PVE.Survivor
{
    public class BattleUnit : IClass
    {
        protected RenderComponent renderComponent;
        private NormalAttackComponent normalAttackComponent;
        protected HudComponent hudComponent;
        protected NavmeshComponent navmeshComponent;
        private SkillComponent skillComponent;
        private BehaviorComponent behaviorComponent;
        private KnockBackComponent knockBackComponent;
        private ControlActionComponent controlActionComponent;
        private PassiveSkillComponent passiveSkillComponent;
        protected CollisionComponent collisionComponent;
        
        private List<ComponentBase> components = new List<ComponentBase>();

        public int unitId;
        public int team;
        public Vector3 position;
        private Vector3 targetPosition;
        protected Vector3 forward;
        private Vector3 targetForward;

        private BattleUnit aimTarget;

        public float lastHitTime;

        public bool isBoss => config != null && config.is_boss > 0;

        public BattleUnit target
        {
            set
            {
                m_target = value;
            }
            get => m_target;
        }
        private BattleUnit m_target;
        
        public BattleUnit teamTarget;
        public Transform Transform;
        public Transform AimPoint;
        public GameObject Root;
        public Transform gunPoint;
        public List<Transform> gunPoints;
        public List<Transform> hitPoints;

        public BattleHeroConfig config;
        public int heroId;
        
        public int consumedAmmoCount;

        public int totalHp;
        public int currentHp;
        public int attack;
        public int defence;
        
        public int currentMp;
        public int totalMp;
        public float criticalRate;
        
        public bool isDead;
        public float deadTime;

        public float collisionRadius = BattleConstValue.UnitCollisionRadius;
        
        public BattleEnemyAIConfig aiConfig;
        public EBehaviorState behaviorState;
        
        public TeamGroup teamGroup;
        public bool isAiming = false;
        public bool isManualMoving = false;
        public bool isInteracting = false;

        public int indexInUnitManager = -1;
        public int indexInSpawner = -1;

        protected int searchTeamMask;

        public int indexInTeam = -1;
        
        public int resId;

        public BattleUnit summonParent;
        public bool isSummonUnit;
        public Vector3 summonOffset;
        public Action onHpChange;
        public Action onPositionChange;
        
        public float hudOffset = 0;

        public bool isLockHp = false;
        
        public bool IsMainUnit
        {
            set
            {
                isMainUnit = value;
            }
            get => isMainUnit;
        }

        private bool isMainUnit;

        public bool locked = false;
        public int fogId;

        public int specialIndex;

        //特殊技能的目标
        public Transform aimFakeTarget;
        public Transform aimRealTarget;
        private float aimAngleSpeed;
        private Vector3 aimForward = BattleConstValue.DEFAULT_POINT;
        private bool isSpecialAiming = false;

        public Vector3 SpecialAimForward => aimForward;
        
        public Action<GameObject> rendererReadyCallback;

        public Vector3 AimForward
        {
            get
            {
                if (renderComponent != null)
                {
                    if (isAiming)
                    {
                        var forward = renderComponent.GetAimForward();
                        forward.y = 0;
                        return forward;
                    }
                }
                return Forward;
            }
        }

        public float AttackValue => attack;
        public float DefenceValue => defence;
        
        public float TotalHp => totalHp;
        
        public bool canBeTarget = true;

        public int uncontrollable = 0;
        
        public Transform GetHitPoint(int index = -1)
        {
            if (hitPoints != null && hitPoints.Count > 0)
            {
                if (index >= 0 && hitPoints.Count > index)
                {
                    return hitPoints[index];
                }

                if (hitPoints.Count > 1)
                {
                    index = UnityEngine.Random.Range(1, hitPoints.Count);
                }
                else
                {
                    index = 0;
                }
                return hitPoints[index];
            }
            return AimPoint;
        }
        
        public Vector3 BattlePosition
        {
            get
            {
                if (teamGroup != null)
                {
                    return teamGroup.Position;
                }
                else
                {
                    return position;
                }
            }
        }

        public Transform GetGunPoint(int index)
        {
            Transform result = AimPoint;
            if (gunPoints != null && index < gunPoints.Count)
            {
                result = gunPoints[index];
            }
            else if (gunPoint != null)
            {
                result = gunPoint;
            }

            if (result == null)
            {
                BattleDebug.LogError(unitId + " " + heroId +"枪口点为空 " + index + " " + AimPoint + " " + gunPoint + " " + gunPoints);
                result = Transform;
            }
            return result;
        }
        
        public virtual void Initialize()
        {
            //BattleDebug.Log("初始化单位 " + unitId);
            locked = false;
            isDead = false;
            CanAttack = true;
            Root = new GameObject("BattleUnit " + unitId);
            Root.transform.SetParent(SurvivorManager.Instance.Root);
            Root.transform.position = position;
            AimPoint = new GameObject("AimPoint").transform;
            AimPoint.parent = Root.transform;
            AimPoint.localPosition = new Vector3(0, 1, 0);
            gunPoint = AimPoint;
            Transform = Root.transform;
            searchTeamMask = BattleHelper.GetTeamMask(team,true);
            isLockHp = team == 0 && BattleConstValue.IsLockSelfHp(StageManager.Instance.stageId);
            InitHero();
            InitComponents();
            finishInitialize();
        }

        void finishInitialize()
        {
            HeroEventBubbleManager.Instance.Active(unitId);
        }

        public float searchRange;
        private bool transmitToGroup;
        public int enemyGroupId;
        public EEnemyAIType aiType;
        
        public List<BattleUnit> summonUnits = new List<BattleUnit>();

        public string Name
        {
            get
            {
                if (config != null)
                {
                    return config.name;
                }
                return string.Empty;
            }
        }
        
        public void InitAI(EEnemyAIType aiType,float searchRange = 0,bool transmitToGroup = false)
        {
            this.searchRange = searchRange;
            this.transmitToGroup = transmitToGroup;
            this.aiType = aiType;
            behaviorComponent?.InitAI(aiType);
        }

        public virtual void InitHero()
        {
            summonUnits.Clear();
            consumedAmmoCount = 0;
            config = BattleConfigManager.Instance.GetHeroConfig(heroId);
            hudOffset = config.hud_offset;
            configMoveSpeed = config.move_speed;
            resId = config.res_id;
            BattleResourceManager.Instance.LoadSoundBank(config.sound_bank);
            InitAttribute();
            //检查是否需要召唤
            if (config.summon_id > 0)
            {
                summonUnits.Add(UnitManager.Instance.CreateSummonUnit(this, config.summon_id));
            }

            if (config.IsBossFocus())
            {
                StageManager.Instance.ShowBossCamera(Transform,forward);
                StageManager.Instance.OnAddBoss(this);
            }

            if (config.IsBossWarning())
            {
                StageManager.Instance.ShowBossWarning(config.name);
            }
            InitElements();
        }
        
        public virtual void InitComponents()
        {
            renderComponent = AddComponent<RenderComponent>();
            behaviorComponent = AddComponent<BehaviorComponent>();
            normalAttackComponent = AddComponent<NormalAttackComponent>();
            hudComponent = AddComponent<HudComponent>();
            if (SurvivorManager.isNavMesh)
            {
                navmeshComponent = AddComponent<NavmeshComponent>();
            }
            skillComponent = AddComponent<SkillComponent>();
            knockBackComponent = AddComponent<KnockBackComponent>();
            controlActionComponent = AddComponent<ControlActionComponent>();
            passiveSkillComponent = AddComponent<PassiveSkillComponent>();
            collisionComponent = AddComponent<CollisionComponent>();
        }

        private void InitElements()
        {
            if (config.birth_element != null)
            {
                for (int i = 0; i < config.birth_element.Count; i++)
                {
                    AddElement(config.birth_element[i],this,null);
                }
            }
        }

        private void InitAttribute()
        {
            var useConfigAttribute = true;
            totalMp = 100;
            var attackRatio = 1f;
            var defRatio = 1f;
            var hpRatio = 1f;
            if (team == 0)
            {
                //从lua获取英雄的属性
                var heroAttribute = new BattleHeroAttribute();
                heroAttribute.heroId = heroId;
                ResidentHandler.Inst.GetFunction("L_SurvivorManager.GetHeroAttribute").Action(heroAttribute);
                if (heroAttribute.valid)
                {
                    useConfigAttribute = false;
                    currentHp = heroAttribute.hp;
                    attack = heroAttribute.attack;
                    defence = heroAttribute.defence;
                }
            }
            else if (team == 2)
            {
                var ratio = StageManager.Instance.missionConfig.attribute_ratio;
                attackRatio = StageManager.Instance.missionConfig.attribute_ratio_atk * ratio;
                defRatio = StageManager.Instance.missionConfig.attribute_ratio_def * ratio;
                hpRatio = StageManager.Instance.missionConfig.attribute_ratio_hp * ratio;
            }
            if (useConfigAttribute)
            {
                currentHp = (int)(config.hp * hpRatio);
                attack = (int)(config.attack * attackRatio);
                defence = (int)(config.defence * defRatio);
            }
            //BattleDebug.Log(heroId + " 英雄属性: hp = " + currentHp + "; attack = " + attack + "; defence = " + defence);
            if (currentHp == 0)
            {
                BattleDebug.LogError("英雄 " + heroId + " 血量为0");
                currentHp = 1;
            }
            totalHp = currentHp;
            shieldValue = 0;
            criticalRate = config.critical_rate;
            currentMp = 0;
            onHpChange?.Invoke();
            uncontrollable = 0;
        }

        public void RemoveCollider()
        {
            collisionComponent?.RemoveCollider();
        }
        
        protected T AddComponent<T>() where T : ComponentBase, new()
        {
            var component = ClassManager.Get<T>();
            component.Initialize(this);
            components.Add(component);
            return component;
        }
        
        public Vector3 TargetPosition
        {
            get => targetPosition;
            set
            {
                targetPosition = value;
            }
        }

        private bool isMovingToTarget;

        public bool positionLocked;
        
        public Vector3 Position
        {
            get => position;
            set
            {
                position = value;
                Transform.position = position;
                navmeshComponent?.SetPosition(position);
            }
        }

        public void SetRenderPosition(Vector3 position,Vector3 forward)
        {
            renderComponent?.SetRenderPosition(position,forward);
        }

        public Vector3 Forward
        {
            get => forward;
            set
            {
                forward = value;
                if (renderComponent != null)
                {
                    renderComponent.Forward = forward;
                }
            }
        }

        public Vector3 GetSummonPosition()
        {
            return summonParent.position + summonOffset;
        }

        public Vector3 GetFlyTextPosition()
        {
            var position = Position;
            position.y += 1.5f;
            var cameraForward = CameraManager.Instance.CameraForward;
            var horizontal = Quaternion.AngleAxis(90,Vector3.up) * cameraForward.normalized * Random.Range(-0.5f,0.5f);
            var vertical = new Vector3(0,Random.Range(-0.5f,0.5f),0);
            return position + horizontal + vertical - cameraForward.normalized * 0.2f;
        }
        
        public void SetPositionValue(Vector3 position)
        {
            this.position = position;
        }
        
        public Vector3 manualMovingDirection;

        public Vector3 TargetForward
        {
            get => targetForward;
            set
            {
                value.y = 0;
                if (value != Vector3.zero)
                {
                    targetForward = value;
                }
            }
        }

        private Vector3 lastPosition;
        
        public void Update()
        {
            var movingToTarget = isMovingToTarget;
            isMovingToTarget = false;
            UpdateMovement();
            for(int i = 0; i < components.Count; i++)
            {
                components[i].Update();
            }
            UpdateForward();
            UpdateElements();
            if (!isMovingToTarget && movingToTarget)
            {
                StopMove();
            }

            if (this.aimTarget != null && aimTarget.isDead && !IsInSkill())
            {
                this.EndAim();
            }
            UpdateSpecialAim();
            OnUpdate();
        }

        protected virtual void OnUpdate()
        {
            
        }

        public void LateUpdate()
        {
            for(int i = 0; i < components.Count; i++)
            {
                components[i].LateUpdate();
            }

            if (!isDead && onPositionChange != null && lastPosition != position)
            {
                onPositionChange.Invoke();
                lastPosition = position;
            }
        }

        private float angleSpeed = 600;
        private void UpdateForward()
        {
            if (positionLocked)
            {
                return;
            }
            if (targetForward != Vector3.zero && targetForward != forward)
            {
                var angle = PveUtils.GetAngle(forward, targetForward);
                var angleThisFrame = angleSpeed * Time.deltaTime;
                if (Mathf.Abs(angle) < angleThisFrame)
                {
                    Forward = targetForward;
                }
                else
                {
                    if (angle < 0)
                    {
                        angleThisFrame = -angleThisFrame;
                    }
                    Forward = Quaternion.AngleAxis(angleThisFrame, Vector3.up) * forward;
                }
            }
        }

        public void Play(string name,bool isFullBody = false,bool resetAction = true)
        {
            //BattleDebug.LogError(unitId + " " + name);
            renderComponent?.Play(name,isFullBody,resetAction);
        }

        public void SetFloat(string name, float value)
        {
            renderComponent?.SetFloat(name,value);
        }
        
        public void SetBool(string name, bool value)
        {
            renderComponent?.SetBool(name,value);
        }

        public float moveSpeed
        {
            get
            {
                return configMoveSpeed * moveSpeedRatio;
            }
        }

        public float moveSpeedRatio = 1;
        public float configMoveSpeed = 4;
        public float shieldValue = 0;
        
        public void SetAgentTargetPosition(Vector3 position)
        {
            navmeshComponent?.SetAgentTargetPosition(position);
        }

        public void SetAgentStopped(bool isStopped)
        {
            navmeshComponent?.SetAgentStopped(isStopped);
        }
        
        private void UpdateMovement()
        {
            if (isDead)
            {
                return;
            }

            if (isSummonUnit)
            {
                isManualMoving = summonParent.isManualMoving;
                var summonPosition = GetSummonPosition();
                var diff = summonPosition - position;
                if (diff.sqrMagnitude > 5f * 5f)
                {
                    Position = summonPosition;
                }
                else
                {
                    if (isManualMoving)
                    {
                        TargetPosition = BattleHelper.MoveByNavMesh(position, GetSummonPosition(), moveSpeed);
                        manualMovingDirection = summonParent.manualMovingDirection;
                    }
                }
            }
        }

        public void SetSpeed(float speed)
        {
            renderComponent?.SetSpeed(speed);
        }

        public void Reload()
        {
            //renderComponent.EndAim();
            normalAttackComponent.Reload();
        }

        public bool IsTargetInRange()
        {
            var distance = Vector3.Distance(target.position, BattlePosition);
            return distance <= normalAttackComponent.attackRange;
        }

        public float GetAttackRange()
        {
            return normalAttackComponent.attackRange;
        }
        
        public bool IsTargetOutOfMaxRange()
        {
            if (team == 2)
            {
                return false;
            }
            if (target != null)
            {
                var distance = Vector3.Distance(target.position, BattlePosition);
                return distance > normalAttackComponent.attackRange + 2;
            }
            return true;
        }

        public void MoveToTarget()
        {
            targetPosition = target.position;
            SetAgentStopped(false);
            SetAgentTargetPosition(targetPosition);
            isMovingToTarget = true;
        }

        public void StopMove()
        {
            TargetPosition = default;
            if (IsNavmeshAgentActive())
            {
                SetAgentStopped(true);
                SetAgentTargetPosition(position);
            }
            isMovingToTarget = false;
        }
        
        public void StopShoot()
        {
            return;
            normalAttackComponent.StopNormalAttack();
            renderComponent.EndAim();
            Play("Idle");
            isAiming = false;
        }

        public void EndAim()
        {
            //BattleDebug.LogError(unitId + " 结束瞄准");
            aimTarget = null;
            renderComponent?.EndAim();
            isAiming = false;
        }

        public virtual void StartAim(BattleUnit target = null,bool useStartPoint = true)
        {
            target ??= this.target;
            if (target == this)
            {
                EndAim();
                return;
            }
            aimTarget = target;
            //BattleDebug.LogError(unitId + " 开始瞄准 " + target.unitId);
            renderComponent?.StartAim(target.AimPoint,useStartPoint);
            isAiming = true;
        }
        
        public void StartShoot()
        {
            if (isDead||CanAttack==false)
            {
                return;
            }
            if (normalAttackComponent.CanNormalAttack())
            {
                normalAttackComponent.StartNormalAttack(target);
                isAiming = true;
                hudComponent?.HideBubble();
            }
            else
            {
                normalAttackComponent.NormalAttackCD();
            }
        }

        public void UpdateShoot()
        {
            normalAttackComponent.UpdateNormalAttack();
        }

        public bool IsAmmoEmpty()
        {
            return normalAttackComponent.IsAmmoEmpty();
        }

        public bool IsReloading()
        {
            return normalAttackComponent.IsReloading();
        }

        public bool HasTeamTarget()
        {
            if (teamTarget != null)
            {
                if (teamTarget.isDead)
                {
                    teamTarget = null;
                    return false;
                }
                else
                {
                    return true;
                }
            }
            return false;
        }

        public bool HasTarget()
        {
            if (target != null)
            {
                if (target.isDead)
                {
                    target = null;
                    return false;
                }
                else if (team == 0 && !IsTargetInRange())
                {
                    target = null;
                    return false;
                }
                else
                {
                    return true;
                }
            }
            return false;
        }

        public bool CanMoveToTarget()
        {
            if (team == 0)
            {
                return false;
            }

            if (IsShooting())
            {
                return false;
            }
            return true;
            /*if (IsShooting())
            {
                return IsTargetOutOfMaxRange();
            }
            else
            {
                return true;
            }*/
        }

        public bool IsShooting()
        {
            return normalAttackComponent.IsInSkill();
        }

        public virtual void ShowBubble()
        {
            hudComponent?.ShowBubble();
        }
        
        private bool hasIgnoreRangeSearch = false;
        
        public void SearchBattlePoint()
        {
            var point = UnitManager.Instance.battlePoint;
            if (Vector3.Distance(point, position) < searchRange)
            {
                behaviorState = EBehaviorState.Battle;
                SearchTarget();
            }
        }
        
        public void SearchTarget()
        {
            var searchRange = 999f;
            if (behaviorState == EBehaviorState.Battle)
            {
                searchRange = 999f;
            }
            else
            {
                searchRange = this.searchRange;
            }

            var lastTarget = target;
            target = UnitManager.Instance.SearchTarget(this,searchTeamMask,EBattleSkillSearchSort.Near,searchRange);
            if (lastTarget != target)
            {
                //BattleDebug.LogError(unitId + " 索敌成功 " + (target==null?"null":target.unitId.ToString()) + searchRange);
                if (target != null)
                {
                    if (transmitToGroup)
                    {
                        UnitManager.Instance.SetTargetToGroup(enemyGroupId,target);
                    }
                }
                behaviorState = EBehaviorState.Battle;
            }
        }

        public bool AutoCastSkill()
        {
            skillComponent.AutoCastSkill();
            var success = skillComponent.IsInSkill();
            return success;
        }

        public bool IsSkillReady()
        {
            if (!CanAttack)
            {
                return false;
            }

            if (normalAttackComponent != null && normalAttackComponent.IsInSkill())
            {
                return false;
            }
            return skillComponent.IsSkillReady();
        }

        public bool IsInSkill()
        {
            return skillComponent.IsInSkill();
        }
        
        public void UpdateSkill()
        {
            skillComponent.UpdateSkill();
        }

        public void UpdateShieldProgress()
        {
            hudComponent?.UpdateShieldProgress(shieldValue / (float)totalHp);
        }

        
        public void SetHpChange(int hpChange)
        {
            if (hpChange < 0)
            {
                if (shieldValue > 0)
                {
                    if (shieldValue >= -hpChange)
                    {
                        shieldValue += hpChange;
                        UpdateShieldProgress();
                        return;
                    }
                    else
                    {
                        hpChange += (int)shieldValue;
                        shieldValue = 0;
                        UpdateShieldProgress();
                    }
                }
            }

            if (isLockHp)
            {
                if (hpChange < 0 && (float)currentHp / totalHp < 0.5f)
                {
                    hpChange /= 2;
                }
                currentHp += hpChange;
                currentHp = Mathf.Clamp(currentHp, (int)(0.2f * totalHp), totalHp);
            }
            else
            {
                currentHp += hpChange;
                currentHp = Mathf.Clamp(currentHp, 0, totalHp);
            }
            hudComponent?.UpdateHpProgress(currentHp / (float)totalHp);
            renderComponent?.OnHpChange();
            OnHpChanged();
            onHpChange?.Invoke();
            if (currentHp <= 0)
            {
                Dead();
            }
        }

        public void OnHit()
        {
            if (behaviorState != EBehaviorState.Battle)
            {
                behaviorState = EBehaviorState.Battle;
            }
            ShowFlash();
        }

        public bool HasMainSkill()
        {
            return skillComponent != null && skillComponent.hasMainSkill;
        }

        protected virtual void OnHpChanged()
        {
            
        }
        
        public void SetMpChange(int mpChange)
        {
            if (isSummonUnit)
            {
                summonParent.SetMpChange(mpChange);
                return;
            }
            //判断单位是否有技能
            if (!HasMainSkill())
            {
                return;
            }
            currentMp += mpChange;
            currentMp = Mathf.Clamp(currentMp, 0, totalMp);
            hudComponent?.UpdateMpProgress(currentMp / (float)totalMp);
        }
        
        protected virtual void OnDead()
        {
            
        }
        
        public void Dead()
        {
            if (isDead)
            {
                return;
            }

            if (isBoss)
            {
                //boss特殊处理，防止撞墙，进行一次navmesh检测
                Forward = BattleHelper.GetBossDeathForward(position,forward);
                renderComponent?.RefreshForward();
            }
            deadTime = TimeManager.time;
            Play("Dead");
            isDead = true;
            OnDead();
            for (int i = 0; i < components.Count; i++)
            {
                components[i].Dead();
            }
            RemoveAllElement();
            UnitManager.Instance.UnitDead(this);
        }

        private List<ElementBase> elementList = new List<ElementBase>();

        public bool IsUncontrollable()
        {
            return uncontrollable > 0;
        }
        
        protected virtual bool CheckCanAddElement(ElementConfig elementConfig)
        {
            if (IsUncontrollable() && elementConfig.main_type == (int)EBattleElementMainType.Control)
            {
                return false;
            }
            return true;
        }
        
        public void AddElement(int elementId, BattleUnit source,Bullet bullet)
        {
            ElementConfig config = BattleConfigManager.Instance.GetElementConfig(elementId);
            if (config == null)
            {
                BattleDebug.LogError("缺少 配表数据 elementID " + elementId);
                return;
            }
            if (!CheckCanAddElement(config))
            {
                return;
            }
            for (int i = elementList.Count - 1; i >= 0; i--)
            {
                var ele = elementList[i];
                if (ele.config.id == config.id)
                {
                    switch (config.conflict)
                    {
                        case (int)EElementConflictType.NoCover:
                            return;
                        case (int)EElementConflictType.Layer:
                            ele.addStack();
                            return;
                        case (int)EElementConflictType.Coexist:
                            break;
                        case (int)EElementConflictType.NewCover:
                           RemoveElementByIndex(i);
                            break;
                    }
                }
                else if (config.group != 0)
                {
                    if (ele.config.group == config.group)
                    {
                        if (ele.config.conflict_value > config.conflict_value)
                        {
                            return;
                        }
                        else
                        {
                            RemoveElementByIndex(i);
                        }
                    }
                }
            }
            var element = BattleFactory.Instance.CreateElement(config);
            element.Initialize(config,source,this,bullet);
            element.Execute();
            if (config.clear_effect?.Count > 0)
            {
                var clr = config.clear_effect[0];
                if (clr.x == 1)
                {
                    RemoveElement((int)clr.y);
                }
            }

            if (element.IsImmediate())
            {
                element.Free();
                return;
            }
            else
            {
                elementList.Add(element);
            }
        }

        public void RemoveElement(int eleCfgID)
        {
            for (int i = elementList.Count - 1; i >= 0; i--)
            {
                var ele = elementList[i];
                if (ele.config.id == eleCfgID)
                {
                    ele.Free();
                    elementList.RemoveAt(i);
                }
            }
        }

        public void RemoveElementByIndex(int index)
        {
            if (elementList.Count > index)
            {
                var ele = elementList[index];
                ele.Free();
                elementList.RemoveAt(index);
            }
        }

        public void RemoveAllElement()
        {
            if (elementList.Count > 0)
            {
                foreach (var VARIABLE in elementList)
                {
                    VARIABLE.Free();
                }
                elementList.Clear();
            }
        }
        
        public void AddSpeedRatio(float ratio)
        {
            moveSpeedRatio += ratio;
            navmeshComponent?.OnMoveSpeedChanged();
        }

        public void AddShield(float value)
        {
            shieldValue += value;
            shieldValue = Mathf.Max(shieldValue,0);
            UpdateShieldProgress();
        }

        private Dictionary<int,int> bulletReplaceIdMap = new Dictionary<int, int>();
        private Dictionary<int,int> bulletExtraIdMap = new Dictionary<int, int>();
        private Dictionary<int,PassiveSkill> childSkillMap = new Dictionary<int, PassiveSkill>();
        public int GetBulletId(int bulletId)
        {
            if (bulletReplaceIdMap.Count > 0 && bulletReplaceIdMap.TryGetValue(bulletId,out var id))
            {
                //UnityEngine.Debug.LogError("子弹替换成功 " + bulletId + " -> " + id);
                return id;
            }
            return bulletId;
        }

        public int GetExtraBulletId(int bulletId)
        {
            if (bulletExtraIdMap.Count > 0 && bulletExtraIdMap.TryGetValue(bulletId,out var id))
            {
                return id;
            }
            return 0;
        }
        
        public void SetReplaceBullet(int before,int after)
        {
            if (after >= 0)
            {
                bulletReplaceIdMap[before] = after;
            }
            else
            {
                bulletReplaceIdMap.Remove(before);
            }
        }

        public void SetExtraBullet(int before, int after)
        {
            if (after >= 0)
            {
                bulletExtraIdMap[before] = after;
            }
            else
            {
                bulletExtraIdMap.Remove(before);
            }
        }

        public PassiveSkill GetExtraChildSkill(int skillId)
        {
            if (childSkillMap.TryGetValue(skillId, out var skill))
            {
                if (skill.valid)
                {
                    return skill;
                }
            }
            return null;
        }

        public void AddChildSkill(int skillId, int childSkillId)
        {
            if (childSkillMap.TryGetValue(skillId, out var skill))
            {
                skill.valid = true;
                //BattleDebug.LogError("已经有技能 " + skillId);
                return;
            }
            skill = ClassManager.Get<PassiveSkill>();
            var childSkillConfig = BattleConfigManager.Instance.GetSkillConfig(childSkillId);
            skill.Initialize(childSkillConfig,this);
            skill.valid = true;
            childSkillMap[skillId] = skill;
        }
        
        public void RemoveChildSkill(int skillId,int childSkillId)
        {
            if (childSkillMap.TryGetValue(skillId, out var skill))
            {
                skill.valid = false;
            }
        }

        private void UpdateElements()
        {
            for (int i = 0; i < elementList.Count; i++)
            {
                var element = elementList[i];
                if (element.NeedDispose())
                {
                    element.Free();
                    //跟最后一个交换
                    if (i != elementList.Count - 1)
                    {
                        elementList[i] = elementList[elementList.Count - 1];
                        i--;
                    }
                    elementList.RemoveAt(elementList.Count - 1);
                }
                else
                {
                    element.Update();
                }
            }
        }

        public void Dispose()
        {
            positionLocked = false;
            rendererReadyCallback = null;
            //BattleDebug.Log("销毁单位 " + unitId);
            for (int i = 0; i < components.Count; i++)
            {
                ClassManager.Free(components[i]);
            }
            components.Clear();
            for (int i = 0; i < elementList.Count; i++)
            {
                elementList[i].Free();
                ClassManager.Free(elementList[i]);
            }
            elementList.Clear();
            bulletReplaceIdMap.Clear();
            if (Root != null)
            {
                GameObject.Destroy(Root);
                Root = null;
            }
            passiveSkillComponent = null;
            hudComponent = null;
            navmeshComponent = null;
            renderComponent = null;
            behaviorComponent = null;
            normalAttackComponent = null;
            skillComponent = null;
            knockBackComponent = null;
            controlActionComponent = null;
            collisionComponent = null;
            position = default;
            targetPosition = default;
            targetForward = default;
            target = null;
            teamTarget = null;
            Transform = null;
            AimPoint = null;
            gunPoint = null;
            gunPoints = null;
            hitPoints = null;
            config = null;
            aiConfig = null;
            teamGroup = null;
            isAiming = false;
            isManualMoving = false;
            isInteracting = false;
            indexInUnitManager = -1;
            indexInSpawner = -1;
            searchTeamMask = 0;
            resId = 0;
            isMainUnit = false;
            locked = false;
            fogId = 0;
            specialIndex = 0;
            unitId = 0;
            indexInTeam = -1;
            isSpecialAiming = false;
            aimFakeTarget = null;
            aimRealTarget = null;
            aimForward = default;
            aimAngleSpeed = 0;
            isMovingToTarget = false;
            deadTime = 0;
            collisionRadius = 0;
            aiType = 0;
            searchRange = 0;
            transmitToGroup = false;
            enemyGroupId = 0;
            isSummonUnit = false;
            summonParent = null;
            summonUnits.Clear();
            canBeTarget = true;
            onHpChange = null;
            isLockHp = false;
            onPositionChange = null;
            onHpChange = null;
        }

        public void InitNavmeshComponent()
        {
            navmeshComponent?.InitAgent();
        }

        public bool canManualMoving = true;
        public Vector3 cachedTargetPosition = BattleConstValue.DEFAULT_POINT;

        public void StartMove(int moveType)
        {
            behaviorComponent.StartMove(moveType);
            normalAttackComponent.StopNormalAttack();
            skillComponent.StopSkill();
            canManualMoving = false;
            isInteracting = true;
        }

        public void EndMove()
        {
            behaviorComponent.EndMove();
            canManualMoving = true;
            isInteracting = false;
        }
        
        public void MoveToInteractable(Vector3 point,Vector3 targetForward)
        {
            //BattleDebug.LogError(unitId + " 开始前往交互点 " + point);
            behaviorComponent.MoveToInteractable(point,targetForward);
            normalAttackComponent.StopNormalAttack();
            skillComponent.StopSkill();
            canManualMoving = false;
            isInteracting = true;
        }
        
        public void StartInteractByMission(Vector3 point)
        {
            //BattleDebug.LogError(unitId + " 开始前往交互点 " + point);
            behaviorComponent.StartInteractByMission(point);
            normalAttackComponent.StopNormalAttack();
            skillComponent.StopSkill();
            canManualMoving = false;
            isInteracting = true;
        }

        public void StopInteractByMission()
        {
            if (!isInteracting)
            {
                return;
            }
            behaviorComponent.StopInteractByMission();
            canManualMoving = true;
            isInteracting = false;
        }
        
        public void SetNavmeshAgentActive(bool active,bool selfRVO = false)
        {
            //selfRVO = SurvivorManager.isNavmeshActive;
            navmeshComponent?.SetAgentActive(active,selfRVO);
        }
        
        public bool IsNavmeshAgentActive()
        {
            return navmeshComponent != null && navmeshComponent.IsAgentActive();
        }
        
        public void SetKnockBack(float distance,float time,Vector3 direction)
        {
            knockBackComponent?.SetKnock(distance,time,direction);
        }

        public bool CanMove => !isDead && !IsInControl();

        public bool IsInControl()
        {
            var isKnocking = knockBackComponent != null && knockBackComponent.IsKnocking();
            var isInControlAction = controlActionComponent != null && controlActionComponent.IsInControl();
            return isKnocking || isInControlAction;
        }

        public bool CanAttack = true;
        
        public void SetRenderEnabled(bool enabled)
        {
            renderComponent?.SetEnabled(enabled);
        }

        public void OnLightElementChange()
        {
            renderComponent?.OnLightElementChange();
        }

        public void DisableAgent()
        {
            navmeshComponent?.SetAgentValid(false);
        }

        public void ShowFlash()
        {
            renderComponent?.Flash();
        }

        public float AddControlAction(ControlElement element)
        {
            if (controlActionComponent != null)
            {
                var dur = controlActionComponent.AddAction(element);
                CanAttack = !controlActionComponent.IsInControl(); //目前击飞和冰冻都无法攻击
                if (CanAttack == false)
                {
                    normalAttackComponent.StopNormalAttack();
                    skillComponent.StopSkill();
                }

                return dur;
            }

            return 0;
        }

        public void RemoveControlAction(ControlElement element)
        {
            if (controlActionComponent != null)
            {
                controlActionComponent.RemoveAction(element);
                CanAttack = !controlActionComponent.IsInControl(); //目前击飞和冰冻都无法攻击
            }
            else
            {
                CanAttack = true;
            }
        }

        public void OnCameraChanged()
        {
            hudComponent?.OnCameraChanged();
        }

        public void ShowChatBubble(string content, int type, float duration = 0)
        {
            if (duration <= 0)
            {
                hudComponent?.ShowChatBubble(content, type);
            }
            else
            {
                hudComponent?.ShowChatBubbleDuration(content, type, duration);
            }
        }

        public void HideChatBubble()
        {
            hudComponent?.HideChatBubble();
        }

        private float lastCheckWallBlockTime;
        
        public bool IsTargetBlockByWall()
        {
            if (lastCheckWallBlockTime + 0.5f > TimeManager.time)
            {
                return true;
            }
            if (BattleHelper.IsBlockByWall(position + new Vector3(0,0.5f,0),target.position + new Vector3(0,0.5f,0)))
            {
                lastCheckWallBlockTime = TimeManager.time;
                return true;
            }
            else
            {
                lastCheckWallBlockTime = -1;
                return false;
            }
        }
        
        public void Trigger(EPassiveTriggerType triggerType)
        {
            passiveSkillComponent?.Trigger(triggerType);
        }

        public void HideWeapon(int index)
        {
            renderComponent?.HideWeapon(index);
        }

        public void MoveSummonUnit(int moveType)
        {
            for (int i = 0; i < summonUnits.Count; i++)
            {
                var unit = summonUnits[i];
                if (unit != null)
                {
                    if (moveType > 0)
                    {
                        unit.StartMove(moveType);
                    }
                    else
                    {
                        unit.EndMove();
                    }
                }
            }
        }

        public void SummonUnitCastSkill(int id)
        {
            for (int i = 0; i < summonUnits.Count; i++)
            {
                var unit = summonUnits[i];
                if (unit != null)
                {
                    unit.CastPassiveSkill(id);
                }
            }
        }

        public void CastPassiveSkill(int id)
        {
            passiveSkillComponent?.CastSkill(id);
        }
        
        public void StartSpecialAim(Transform target,float angleSpeed = 60)
        {
            this.aimAngleSpeed = angleSpeed;
            aimRealTarget = target;
            if (aimForward == BattleConstValue.DEFAULT_POINT)
            {
                aimForward = target.position - position;
            }

            if (aimFakeTarget == null)
            {
                var aimTargetObject = new GameObject("AimTarget");
                aimFakeTarget = aimTargetObject.transform;
                aimFakeTarget.SetParent(Transform);
            }
            renderComponent.StartAim(aimFakeTarget);
            isSpecialAiming = true;
        }

        private void UpdateSpecialAim()
        {
            if (!isSpecialAiming)
            {
                return;
            }

            aimForward.y = 0;
            var aimTargetForward = aimRealTarget.position - position;
            aimTargetForward.y = 0;
            var angle = PveUtils.GetAngle(aimForward,aimTargetForward);
            var angleThisFrame = aimAngleSpeed * Time.deltaTime;
            if (Mathf.Abs(angle) < angleThisFrame)
            {
                aimForward = aimTargetForward;
            }
            else
            {
                if (angle < 0)
                {
                    angleThisFrame = -angleThisFrame;
                }
                aimForward = Quaternion.AngleAxis(angleThisFrame, Vector3.up) * aimForward;
            }
            aimFakeTarget.position = position + aimForward;
        }
        
        public void EndSpecialAim()
        {
            renderComponent.EndAim();
            aimRealTarget = null;
            isSpecialAiming = false;
            aimForward = BattleConstValue.DEFAULT_POINT;
        }

        public void SetAnimatorSpeed(float speed)
        {
            renderComponent?.SetAnimatorSpeed(speed);
        }
        
        public void OnPause()
        {
            behaviorComponent?.OnPause();
            skillComponent?.StopSkill();
            navmeshComponent?.OnPause();
            renderComponent?.Play("Idle");
            renderComponent?.SetSpeed(0,true);
        }

        public void OnResume()
        {
            navmeshComponent?.OnResume();
            behaviorComponent?.OnResume();
        }

        public void UpdateShadowOffset()
        {
            renderComponent?.UpdateShadowOffset();
        }

        public void SetShowHud(bool show)
        {
            hudComponent?.SetShowHud(show);
        }

        public void ShowPhantom()
        {
            renderComponent?.ShowPhantom();
        }
        
        public void OnReset()
        {
            
        }
    }
}
